#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ = ''
__author__ = 'HaiFeng'
__mtime__ = '2016/11/16'
"""

from flask import render_template, request, jsonify
from flask_login import login_required

from py_at.publicMethod import MyEncoder
from web_flask.app import app,a

from py_at.Tool import IntervalTypetemp
from py_at.Statistics import Statistics
import copy
import json
# @app.route('/static/<path:path>')
# @login_required
# def send_js(path):
#     return send_from_directory('static', path)


@app.route('/')
@app.route('/index')
def index():
    # return app.send_static_file('index.html')
    return 'welcome to at py.'



#
# # 填充data bars 基本废弃2019-2-11 没什么用
# @app.route('/report', methods=['POST'])
# @login_required
# def report():
#     data = json.loads(request.form['data'])
#     bars = json.loads(request.form['bars'])
#     return render_template('report.html', data=data, bars=bars)  # loads后会变为'.
#
#
# @app.route('/echarts')
# @login_required
# def echarts():
#     return render_template('echarts.html')






''' 基本废弃代码 原来的老代码唯一的作用的就是参考下  他的代码写法 还有html里面的使用原生js操作dom的方法  2019-2-11
# 服务器启动加载所有策略  然后这里展示
@app.route('/moniter')
@login_required
def moniter():
    stra_json_array.clear()
    for stra in a.stra_instances:
        stra_json_array.append({
            'id': stra.ID,
            'name': '{0} {1} {2}'.format(stra.Instrument, stra.Interval, stra.IntervalType),
            'params': stra.Params,
        })
    return render_template('moniter.html', stras=stra_json_array)


@app.route('/test_stra', methods=['POST', 'GET'])
@login_required
def test_stra():
    rsp = request.values.to_dict()
    # print(rsp['params'])#返回 ImmutableMultiDict;转成dict后可取到数据

    stra_json = rsp['strategies']
    params = json.loads(rsp['params'])  # str->json

    # 根据返回的标识取对应的策略
    stra = [s for s in a.stra_instances if s.ID == stra_json]
    stra = stra[0]

    # 重新构建实例
    # module = __import__(stra.__module__)  # import module
    # c = getattr(getattr(module, stra.__class__.__name__), stra.__class__.__name__)  # 双层调用才是class,单层是为module
    # stra = c()
    stra = stra.__class__()

    # 重新设置参数
    for p in params:
        print(stra.Params[p])
        stra.Params[p] = params[p]
        print(stra.Params[p])

    a.read_data_test(stra)
    # data, bar_json = Statistics(stra).GetDataAndBars()
    data, bar_json = ""
    return render_template('report.html', data=data, bars=bar_json)
'''

# -----------------------------------------------------------------------------------------------------------
#登陆ctp账户  通过a登陆并初始化日志 然后返回code
@app.route('/login', methods=['POST', 'GET'])
@login_required
def login():
    rsp = request.values.to_dict()
    returnlist = []
    for i in list(rsp.values()):
        a.TradeInit(i)  # 实盘登陆临时放到这里
        returnlist.append(i)
    if len(a.Accounts)==0:
        a.createlogInfo()  # 启动实盘日志输出

    return jsonify({'code': 'success','message':returnlist})


# -----------------------------------------------------------------------------------------------------------
@app.route('/straAdd', methods=['POST', 'GET'])
@login_required
def straAdd():
    '''
     增加新的策略配置
     收到前端数据然后通过a写入配置文件，写入配置文件函数自带同步内存功能
    :return:
    '''
    rsp = request.values.to_dict()
    obj = a.write_strategy_json(rsp)  # 内存和配置文件一块写
    ojbtemp = copy.copy(obj)
    ojbtemp['Instrument'] = ojbtemp['Mappinginstrument'] = obj['Datas'][0]['Instrument']
    ojbtemp['IntervalType'] = IntervalTypetemp[obj['Datas'][0]['IntervalType']]   #'IntervalType.Tick'   格式化为'Tick'
    ojbtemp['Interval'] = obj['Datas'][0]['Interval']
    ojbtemp['id'] = obj['ID']
    return jsonify({'code': 'success', 'obj': ojbtemp})



# ----------------------------------------------------------------------------------------------------------
# 加载所有策略并显示
@app.route('/control')
@login_required
def control():
    '''
    展现策略列表   从内存中加载所有策略配置文件   并返回 下列内容
    stra_json_array=[]
    :return: stra_json_array 策略列表    a.Strageties_name_params 策略名子   a.allInstrument 合约名
    '''
    # 对用户数据进行格式化
    InvestorSetting = a.readInverstorsjson()  # 读取账户配置文件
    templinshi = 0
    stra_json_array=[]
    for k, v in InvestorSetting.items():
        v['secretkey'] = "******"  # 隐藏显示用户key
        v['username'] = k
        v['id'] = templinshi
        if k in a.Accounts:
            v['statusClass'] = "label label-success"
            v['status'] = '已启动'
        else:
            v['statusClass'] = "label label-primary"
            v['status'] = '未启动'
        templinshi = templinshi + 1

    #对策略进行格式户输出

    stra_json_array.clear()
    for k, v in a.CanshuDict.items():
        tringstatus = "false"  # 判断是否已经绑定实盘交易  默认是没有绑定
        position  = {"多":0,"空":0}
        if v.get('stra'):
            position['多']=v.get('stra').PositionLong    #对仓进行填充
            position['空'] = v.get('stra').PositionShort  #对仓进行填充

            if v.get('stra').EnableOrder == True:         #如果已经启动实盘了  那么修改实盘标志
                tringstatus = "true"
        # 构造前台的json
        stra_json_array.append({
            'id': k,
            # 'name': '{0} {1} {2}'.format(stra.Instrument, stra.Interval, stra.IntervalType),
            'Strategy': v['Strategy'],
            'Excange': v['Excange'],
            'Instrument': v['Datas'][0]['Instrument'],
            'Mappinginstrument': v['Datas'][0]['Instrument'],
            'Interval': v['Datas'][0]['Interval'],
            'IntervalType': IntervalTypetemp[v['Datas'][0]['IntervalType']],
            'Params': v['Params'],
            'Position':position,                                      #如果加载了  对这个策略的仓位进行统计并输出
            'Investors': v['Investors'],
            'Loadstatus': "true" if v.get('stra') else "false",
            'Tringstatus': tringstatus,
            'OrderStrateId':v['OrderStrateId']   #订单编号用于区分订单的编号（这个订单属于那个策略发送的） 界面不显示这个
        })
    return render_template('control.html', stras=stra_json_array, strageties=a.Strageties_name_params,
                           allInstrument=[x['InstrumentID'] for x in a.allInstrument],InvestorSetting=list(InvestorSetting.values()),FuturesSetting=list(a.FuturesSetting.keys()))


# ---------------------------------------------------------------------------------------------------------------
@app.route('/allLoad', methods=['POST', 'GET'])
@login_required
def allLoad():
    '''
    加载策略  通过遍历加载实现加载单个或者多个策略
    parasm : list
    :return:
    '''
    rsq = request.values.to_dict()
    position={}
    for v in rsq.values():
        position[v]={}
        a.initstra(v)
        position[v]['多']=a.CanshuDict.get(v).get('stra').PositionLong     #加载完毕之后策略已经有仓位了  在这里把仓位传回给前台
        position[v]['空']=a.CanshuDict.get(v).get('stra').PositionShort   #加载完毕之后策略已经有仓位了  在这里把仓位传回给前台

    # {"code":"success","posiiton":{"20180416152501":{"多":0,"空":1},"20180416152502":{"多":1,"空":0},"20190125131908":{"多":0,"空":1 }}}
    return jsonify({'code': 'success','position':position})


# ---------------------------------------------------------------------------------------------------------------
@app.route('/alltrading', methods=['POST', 'GET'])
@login_required
def alltrading():
    '''
    启动所有实际下单交易
    params:策略id 和策略状态（status）
    :return:
    '''
    messages = "";

    if a.Accounts:     # 判断当前有登陆账户
        rsq = request.values.to_dict()
        status = rsq.pop("status")
        for k in rsq.values():  # 加载所有策略实例
            messages += a.trading(k, status)   #设置策略为可交易 并绑定所有实盘主动以及被动函数
    else:
        messages = "没有登陆任何实盘账户，无法启动策略"
    return jsonify({'code': 'success', 'messages': messages})


# --------------------------------------------------------------------------------------------------------------
#更新策略参数
@app.route('/updateStraParasm', methods=['POST', 'GET'])
@login_required
def saveParams():
    """
    更新策略参数
    如果运行中则停止
    :return:
    """
    rsq = request.values.to_dict()
    print(rsq)
    mesages = a.updateParams(rsq['id'],rsq['paramsname'], eval(rsq['params']))

    if mesages:
        return jsonify({'code': mesages})
    else:
        return jsonify({'code': 'success'})



# ----------------------------------------------------------------------------------------------------------------
#删除策略
@app.route('/deletestra', methods=['POST', 'GET'])
@login_required
def deletestra():
    """
    删除当前策略
    :return:
    """
    rsq = request.values.to_dict()
    messages = a.deletestra(rsq['id'])   #从配置文件以及内存中一并删除
    if not messages:  # 如果返回信息没有任何数据也就是空的话这条成立    上面的都应该这样修改
        message = 'success'
    return jsonify({'code': messages})


# -----------------------------------------------------------------------------------------------------------------
@app.route('/showk', methods=['POST', 'GET'])
@login_required
def showk():
    """
    显示k线
    :return:
    """
    bars = []
    dates = []
    varlist = []
    showline = []
    rsq = request.values.to_dict()
    print(rsq)
    if a.CanshuDict.get(rsq['straid']):
        i = a.CanshuDict.get(rsq['straid'])
        if i.get('stra'):
            stra = i.get('stra')
            statistics = Statistics(stra, a.allInstrument)
            data, bars_json = statistics.GetDataAndBars()
            # eval(json.dumps(data['report'], cls=MyEncoder))  这里通过json.dumps(data['report'], cls=MyEncoder)转换以后就是一个str了   但是前台需求一个对象 所以重新包装为对象然后返回
            return render_template('report.html', data0=bars_json, data1=data['orders'], data2=data['indexes'],
                                   data3=eval(json.dumps(data['report'], cls=MyEncoder)), data4=data['req'],markPointlist = data['markPoint'])
        else:
            return "没有相应的策略"
            #         dates = stra.D.tolist()
            #         for i in range(len(dates)):
            #             bars.append([stra.O[i].tolist(), stra.C[i].tolist(), stra.L[i].tolist(), stra.H[i].tolist()])
            #         varlist = stra.Varlist
            #         showline = getShowkDate(stra.Orders)
            # return render_template("showk.html", bars=bars, dates=dates, showline=showline, varlist=varlist, titletext=(
            #     '%s - %s%s' % (
            #         stra.Instrument, str(stra.Datas[0].Interval), stra.Datas[0].IntervalType)))
            #     #stra.Instrument, str(stra.Datas[0].Interval), IntervalTypetemp[stra.Datas[0].IntervalType].name)))


# ----------------------------------------------------------------------------------------------------------------------
@app.route('/positionCheck', methods=['POST', 'GET'])
@login_required
def showPositionCheck():
    """
    仓位检查页面
    :return:
    """
    return render_template("Positioncheck.html", userlist=list(a.Accounts.keys()) if a.Accounts.keys() else []  ,allInstrument=a.allInstrument)


# ------------------------------------------------------------------------------------------------------------------------------------------------------

@app.route('/selectPosition', methods=['POST', 'GET'])
@login_required
def selectPosition():
    """
    params :#{'userlogic': '包括', 'users': '全部', 'instrumentlogic': '包括', 'select_instrument': '全部'}
    仓位检查实现
    :return:
    """

    req = request.values.to_dict()
    mesages = ""
    Positionlist= []
    if not a.Accounts:
        mesages = "没有登陆账户无法查询实际持仓信息"
    elif not a.real:
        messages = "没有任何策略启动"
    else:                                                               #基本条件满足
        Positionlist=tiaojianSelectPosition(req)                  #根据条件查询仓位
    if mesages:
        return jsonify({'code': mesages})
    else:
        return jsonify({'code': 'success', 'obj': Positionlist})




# --------------------------------------------------------------------------------------------------------------------------------------------------
@app.route('/synchronous', methods=['POST', 'GET'])
@login_required
def synchronous():
    """
    仓位同步
    :return:
    """
    req = request.values.to_dict()
    #message = a.synchronous(req['users'])
    Positionlist = tiaojianSelectPosition(req)  # 根据条件查询仓位
    a.synchronous(Positionlist)     #对仓位进行同步
    return jsonify({'code': 'success'})









#-----------------------------------------------------------------------------------------------------------------------------------------公共方法
def tiaojianSelectPosition(req):
    #根据条件进行重新仓位的查询以及同步
    returnpositionlist = []
    userlist = []
    if req['userlogic'] == '包括':                               #如果包括
        if req['users'] == '全部':                                    #全部
            userlist = a.Accounts.keys()                                    #所有用户都查询
        if not req['users'] == '全部':                                #如果只包括某一个账户
            userlist.append(req['users'])                                         #只查询一个账户 所以只添加一个
    elif req['userlogic'] == "排除":                             #如果条件# 排除
        if req['users'] == '全部':                                    #排除全部
            userlist = []                                               #那就是不用查询 直接是空的
        if not req['users'] == "全部":                                #如果不等于全部 只排除一个
            for i in a.Accounts.keys():
                if i == req['users']:  # 排除这一个                     #添加的时候如果是排除的这个就不添加了
                    continue
                userlist.append(i)                                       #如果不是排除的一个就添加上去
    for i in userlist:                                              #根据上面的条件进行遍历查找仓位
        obj = a.selectPosition( i)
        returnpositionlist.append(obj)                              #保存进返回数据里面

    Positionlist= copy.deepcopy(returnpositionlist)
    #1. copy.copy 浅拷贝 只拷贝父对象，不会拷贝对象的内部的子对象。
    #2. copy.deepcopy 深拷贝 拷贝对象及其子对象
    if req['instrumentlogic'] =='包括':
        if not req['select_instrument']=="全部":  #如果不是包括全部那就是只包括某一个商品
            for index,userposition in enumerate(returnpositionlist):
                for positiontemp in userposition.values():
                    if not positiontemp.get('Instrument')==req['select_instrument']:
                        Positionlist[index].pop(positiontemp.get('Instrument'))


    elif req['instrumentlogic'] =='排除':
        if req['select_instrument']=="全部":
            Positionlist=[]
        elif not req['select_instrument']=="全部":
            tempdelete = []
            for index,userposition in enumerate(returnpositionlist):
                for positiontemp in userposition.values():
                    if positiontemp.get('Instrument')==req['select_instrument']:
                        Positionlist[index].pop(req['select_instrument'])

    return Positionlist

